home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
007
/
bitmanip.cq
/
bitmanip.c
Wrap
C/C++ Source or Header
|
1985-02-06
|
7KB
|
174 lines
/* Some useful bit manipulation functions inspired by the article
* "Binary Magic Numbers" by Edwin E. Freed in DDJ #78, April 1983.
* by Dale Wilson, 1983
* placed in the Public Domain
*
* These functions were written so they may be directly translated
* into assembly language for most computers.
*
* These functions were tested on a Zenith 100 computer using the
* C86 compiler from Computer Innovations, Inc.
*/
#include <stdio.h>
#define TRUE 1/* stranger than fiction */
#define FALSE 0 /* fiction */
#define CNTLZ 26 /* MS-DOS eof */
#define N 16 /* bits per "word" */
#define V 4 /* log 2 of N */
/* Since C does not have binary constants, the binary magic numbers are
* expressed below in hexadecimal. B from Freed's article is divided
* into b1 and b2 since there was no good reason to have them in the
* same array.
*/
unsigned int b1[V] = { 0x5555, 0x3333, 0x0F0F, 0x00FF };
unsigned int b2[V] = { 0xAAAA, 0xCCCC, 0xF0F0, 0xFF00 };
/* converting binary numbers to Gray code is so simple that it may
* be best defined as a macro rather than a function.
*/
#define binary_to_Gray(x) (x ^ x >> 1) /* X exclusive_or X shifted_right 1 */
/* MAIN routine to test the functions.
* Numbers (entered in hexadecimal) will be used as arguments in each
* of the functions. As an additional check, the binary number resulting
* from the Gray_to_binary function will be converted back to Gray code--
* which should result in the original number.
*/
main(argc,argv) int argc; char *argv[];
{ unsigned int r,i;
int c;
while(TRUE) /* loop forever */
{
printf("Enter number: ");
fscanf(stdin,"%x",&i); /* read a hexadecimal */
while((c=getchar()) != '\n') /* discard rest of line */
if(c == EOF || c == CNTLZ) /* except on end of file */
exit(); /* quit */
printf("low clear bit: %d\n", low_clear_bit(i));
printf("high set bit : %d\n", hi_set_bit(i));
printf("side sum : %d\n", side_sum(i));
printf("parity : %d\n", parity (i));
r = Gray_to_binary(i);
printf("Gray code : 0x%04x\n", r);
printf("GTB to Binary: 0x%04x\n", binary_to_Gray(r));
printf("Reversed bits: 0x%04x\n", reverse_bits(i));
putchar('\n'); /* leave a blank line between */
}
}
/* This function returns the bit number of the lowest bit in the word
* which is clear (zero). The least significant bit is numbered 0, the
* bit to the left of that, 1, and so on...
* A minus 1 is returned for words in which all bits are on.
* The time to execute this function is proportional to V which is
* log2 of the number of bits in a word.
* Note that the function low_set_bit may be created by complementing the
* argument and calling low_clear_bit.
*/
low_clear_bit(value) unsigned int value;
{ unsigned int temp;
int i, result;
if((value = ~value) == 0) /* complement, test for zero */
result = -1; /* zero means no clear bits */
else
{ result = 0;
for (i = V-1; i >= 0; i--)
{ result <<= 1; /* make space for next bit */
temp = value & b1[i]; /* test using magic numbers */
if(temp == 0)
result |= 1; /* next bit of result is 1 */
else
value = temp; /* discard disqualified bits */
}
}
return(result);
}
/* This function returns the bit number of the highest bit in the word
* which is set (one). The least significant bit is numbered 0, the
* bit to the left of that, 1, and so on...
* A minus 1 is returned for words in which all bits are off.
* The time to execute this function is proportional to V which is
* log2 of the number of bits in a word.
* Note that the function high_clear_bit may be created by complementing the
* argument and calling high_set_bit.
*/
hi_set_bit(value) unsigned int value;
{ unsigned int temp;
int result, i;
if(value == 0) /* if no bits are on */
result = -1; /* return that info */
else
{ result = 0;
for(i = V-1; i >= 0; i--)
{ result <<= 1; /* space for next bit */
temp = value & b2[i];
if (temp != 0)
{ result |= 1; /* next bit is one */
value = temp; /* discarded unneeded bits */
}
}
}
return(result);
}
/* This function returns a count of the number of bits which are on in a
* word. It executes in a time proportional to V, the log base 2 of the
* number of bits in a word.
* Note that a count of the number of zero bits in the word may be found
* by complementing the value and calling side_sum.
*/
side_sum(value) unsigned int value;
{ int i;
unsigned int s;
s = 1;
for(i=0; i<V; i++) /* use magic in reverse order */
{
value = (value & b1[i]) + ((value >> s) & b1[i]);
s <<= 1; /* generate the powers of two on the fly */
}
return(value);
}
/* This function converts a number expressed in Gray code to the
* equivalent binary number. It executes in time proportional to the
* log base 2 of the number of bits in the word.
*/
Gray_to_binary(value) unsigned int value;
{ unsigned int s;
for(s = N >> 1; s != 0; s >>= 1)
{
value ^= value >> s;
}
return(value);
}
/* This function returns the parity of a word--that is, it returns a zero
* if the number of one bits in the word is even, and a one if the number
* of one bits in the word is odd. The low order bit of the results of
* Gray_to_binary and side_sum both have this property, so isolating this
* bit gives the desired result. Gray_to_binary was selected since it is
* a faster function than side_sum.
*/
parity(value) unsigned int value;
{
return(Gray_to_binary(value) & 1); /* build on previous word */
}
/* This function reverses the bits in a word. Strangely enough, this turns
* out to be a very useful function to have available. Note that this function
* works only on functions with word lengths which are powers of 2.
*/
reverse_bits(value) unsigned int value;
{ unsigned int s,i;
s = 1; /* s provides the powers of 2 */
for(i=0; i<V; i++)